unit drawer;

{$mode objfpc}{$H+}

interface

uses
  // LCL, RTL, FCL
  Classes, SysUtils, Controls, Graphics, Math,
  // TesteDeVisao
  constants, splash;

type
  { TTestDrawer }

  TTestDrawer = class(TCustomControl)
  private
    ImagesNorth, ImagesEast, ImagesSouth,
      ImagesWest: array [0..9] of TPortableNetworkGraphic;
    BufBitmap: TBitmap;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure LoadImages;
    procedure Paint; override;
    procedure DrawTestTable(ACanvas: TCanvas; AX, AY: Cardinal);
    procedure DrawFreiburgOptotype(ACanvas: TCanvas;
     ADirection: TDirection; ADestRect: TRect; ASizeCount: Integer);
    procedure DrawOptotypeSelection(ACanvas: TCanvas; ADestRect: TRect);
    procedure UpdateImage;
  end;

implementation

uses testlogic, config;

{ TDesenhista }

constructor TTestDrawer.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  Randomize();

  BufBitmap := TBitmap.Create;

  LoadImages();
end;

destructor TTestDrawer.Destroy;
begin
  BufBitmap.Free;

  inherited Destroy;
end;

procedure TTestDrawer.LoadImages;
var
  i: Integer;
begin
  FormSplash.UpdateStatus(10, 'Loading PNG images from ' + gTestConfig.Path);

  { Load optotype images }

  FormSplash.UpdateStatus(20, 'Creating image buffer Nr 0');

  ImagesNorth[0] := TPortableNetworkGraphic.Create;
  ImagesNorth[0].LoadFromFile(gTestConfig.Path + 'north_0.png');
  ImagesEast[0] := TPortableNetworkGraphic.Create;
  ImagesEast[0].LoadFromFile(gTestConfig.Path + 'east_0.png');
  ImagesSouth[0] := TPortableNetworkGraphic.Create;
  ImagesSouth[0].LoadFromFile(gTestConfig.Path + 'south_0.png');
  ImagesWest[0] := TPortableNetworkGraphic.Create;
  ImagesWest[0].LoadFromFile(gTestConfig.Path + 'west_0.png');

  FormSplash.UpdateStatus(20 + 1*5, 'Creating image buffer Nr 1');

  ImagesNorth[1] := TPortableNetworkGraphic.Create;
  ImagesNorth[1].LoadFromFile(gTestConfig.Path + 'north_1.png');
  ImagesEast[1] := TPortableNetworkGraphic.Create;
  ImagesEast[1].LoadFromFile(gTestConfig.Path + 'east_1.png');
  ImagesSouth[1] := TPortableNetworkGraphic.Create;
  ImagesSouth[1].LoadFromFile(gTestConfig.Path + 'south_1.png');
  ImagesWest[1] := TPortableNetworkGraphic.Create;
  ImagesWest[1].LoadFromFile(gTestConfig.Path + 'west_1.png');

  FormSplash.UpdateStatus(20 + 2*5, 'Creating image buffer Nr 2');

  ImagesNorth[2] := TPortableNetworkGraphic.Create;
  ImagesNorth[2].LoadFromFile(gTestConfig.Path + 'north_2.png');
  ImagesEast[2] := TPortableNetworkGraphic.Create;
  ImagesEast[2].LoadFromFile(gTestConfig.Path + 'east_2.png');
  ImagesSouth[2] := TPortableNetworkGraphic.Create;
  ImagesSouth[2].LoadFromFile(gTestConfig.Path + 'south_2.png');
  ImagesWest[2] := TPortableNetworkGraphic.Create;
  ImagesWest[2].LoadFromFile(gTestConfig.Path + 'west_2.png');

  FormSplash.UpdateStatus(20 + 3*5, 'Creating image buffer Nr 3');

  ImagesNorth[3] := TPortableNetworkGraphic.Create;
  ImagesNorth[3].LoadFromFile(gTestConfig.Path + 'north_3.png');
  ImagesEast[3] := TPortableNetworkGraphic.Create;
  ImagesEast[3].LoadFromFile(gTestConfig.Path + 'east_3.png');
  ImagesSouth[3] := TPortableNetworkGraphic.Create;
  ImagesSouth[3].LoadFromFile(gTestConfig.Path + 'south_3.png');
  ImagesWest[3] := TPortableNetworkGraphic.Create;
  ImagesWest[3].LoadFromFile(gTestConfig.Path + 'west_3.png');

  FormSplash.UpdateStatus(20 + 4*5, 'Creating image buffer Nr 4');

  ImagesNorth[4] := TPortableNetworkGraphic.Create;
  ImagesNorth[4].LoadFromFile(gTestConfig.Path + 'north_4.png');
  ImagesEast[4] := TPortableNetworkGraphic.Create;
  ImagesEast[4].LoadFromFile(gTestConfig.Path + 'east_4.png');
  ImagesSouth[4] := TPortableNetworkGraphic.Create;
  ImagesSouth[4].LoadFromFile(gTestConfig.Path + 'south_4.png');
  ImagesWest[4] := TPortableNetworkGraphic.Create;
  ImagesWest[4].LoadFromFile(gTestConfig.Path + 'west_4.png');

  FormSplash.UpdateStatus(20 + 5*5, 'Creating image buffer Nr 5');

  ImagesNorth[5] := TPortableNetworkGraphic.Create;
  ImagesNorth[5].LoadFromFile(gTestConfig.Path + 'north_5.png');
  ImagesEast[5] := TPortableNetworkGraphic.Create;
  ImagesEast[5].LoadFromFile(gTestConfig.Path + 'east_5.png');
  ImagesSouth[5] := TPortableNetworkGraphic.Create;
  ImagesSouth[5].LoadFromFile(gTestConfig.Path + 'south_5.png');
  ImagesWest[5] := TPortableNetworkGraphic.Create;
  ImagesWest[5].LoadFromFile(gTestConfig.Path + 'west_5.png');

  FormSplash.UpdateStatus(20 + 6*5, 'Creating image buffer Nr 6');

  ImagesNorth[6] := TPortableNetworkGraphic.Create;
  ImagesNorth[6].LoadFromFile(gTestConfig.Path + 'north_6.png');
  ImagesEast[6] := TPortableNetworkGraphic.Create;
  ImagesEast[6].LoadFromFile(gTestConfig.Path + 'east_6.png');
  ImagesSouth[6] := TPortableNetworkGraphic.Create;
  ImagesSouth[6].LoadFromFile(gTestConfig.Path + 'south_6.png');
  ImagesWest[6] := TPortableNetworkGraphic.Create;
  ImagesWest[6].LoadFromFile(gTestConfig.Path + 'west_6.png');

  FormSplash.UpdateStatus(20 + 7*5, 'Creating image buffer Nr 7');

  ImagesNorth[7] := TPortableNetworkGraphic.Create;
  ImagesNorth[7].LoadFromFile(gTestConfig.Path + 'north_7.png');
  ImagesEast[7] := TPortableNetworkGraphic.Create;
  ImagesEast[7].LoadFromFile(gTestConfig.Path + 'east_7.png');
  ImagesSouth[7] := TPortableNetworkGraphic.Create;
  ImagesSouth[7].LoadFromFile(gTestConfig.Path + 'south_7.png');
  ImagesWest[7] := TPortableNetworkGraphic.Create;
  ImagesWest[7].LoadFromFile(gTestConfig.Path + 'west_7.png');

  FormSplash.UpdateStatus(20 + 8*5, 'Creating image buffer Nr 8');

  ImagesNorth[8] := TPortableNetworkGraphic.Create;
  ImagesNorth[8].LoadFromFile(gTestConfig.Path + 'north_8.png');
  ImagesEast[8] := TPortableNetworkGraphic.Create;
  ImagesEast[8].LoadFromFile(gTestConfig.Path + 'east_8.png');
  ImagesSouth[8] := TPortableNetworkGraphic.Create;
  ImagesSouth[8].LoadFromFile(gTestConfig.Path + 'south_8.png');
  ImagesWest[8] := TPortableNetworkGraphic.Create;
  ImagesWest[8].LoadFromFile(gTestConfig.Path + 'west_8.png');

  FormSplash.UpdateStatus(20 + 9*5, 'Creating image buffer Nr 9');

  ImagesNorth[9] := TPortableNetworkGraphic.Create;
  ImagesNorth[9].LoadFromFile(gTestConfig.Path + 'north_9.png');
  ImagesEast[9] := TPortableNetworkGraphic.Create;
  ImagesEast[9].LoadFromFile(gTestConfig.Path + 'east_9.png');
  ImagesSouth[9] := TPortableNetworkGraphic.Create;
  ImagesSouth[9].LoadFromFile(gTestConfig.Path + 'south_9.png');
  ImagesWest[9] := TPortableNetworkGraphic.Create;
  ImagesWest[9].LoadFromFile(gTestConfig.Path + 'west_9.png');

{  // Possible code to create the images by stretching

  for i := 1 to INT_OPTOTYPESIZE_MAX - 2 do
  begin
    FormSplash.UpdateStatus(20 + i*5, 'Creating image buffer Nr ' + IntToStr(i));

    ImagesNorth[i] := TPortableNetworkGraphic.Create;
    ImagesNorth[i].Width := OptotypeSizes[i];
    ImagesNorth[i].Height := OptotypeSizes[i];
    ImagesNorth[i].Canvas.StretchDraw(
      Bounds(0, 0, OptotypeSizes[i], OptotypeSizes[i]), ImagesNorth[0]);

    ImagesEast[i] := TPortableNetworkGraphic.Create;
    ImagesEast[i].Width := OptotypeSizes[i];
    ImagesEast[i].Height := OptotypeSizes[i];
    ImagesEast[i].Canvas.StretchDraw(
      Bounds(0, 0, OptotypeSizes[i], OptotypeSizes[i]), ImagesEast[0]);

    ImagesSouth[i] := TPortableNetworkGraphic.Create;
    ImagesSouth[i].Width := OptotypeSizes[i];
    ImagesSouth[i].Height := OptotypeSizes[i];
    ImagesSouth[i].Canvas.StretchDraw(
      Bounds(0, 0, OptotypeSizes[i], OptotypeSizes[i]), ImagesSouth[0]);

    ImagesWest[i] := TPortableNetworkGraphic.Create;
    ImagesWest[i].Width := OptotypeSizes[i];
    ImagesWest[i].Height := OptotypeSizes[i];
    ImagesWest[i].Canvas.StretchDraw(
      Bounds(0, 0, OptotypeSizes[i], OptotypeSizes[i]), ImagesWest[0]);
  end;}
end;

procedure TTestDrawer.Paint;
begin
  Canvas.Draw(0, 0, BufBitmap);
end;

procedure TTestDrawer.DrawTestTable(ACanvas: TCanvas; AX, AY: Cardinal);
var
  lRect: TRect;
  lSize, lHeight, lHSpacing, lAmount: Integer;
  i, j: Integer;
begin
  lHeight := INT_TESTDRAWER_VSPACING;

  for i := 0 to 9 do
  begin
    lSize := OptotypeSizes[i];
    lAmount := OptotypeAmounts[i];
    lHSpacing := (INT_TESTDRAWER_WIDTH - lAmount * lSize) div (lAmount - 1);

    for j := 0 to OptotypeAmounts[i] - 1 do
    begin
      lRect := Bounds(
        AX + lHSpacing * j + lSize * j,
        AY + lHeight,
        lSize,
        lSize
      );

      if (i = gTestLogic.State.CurrentRow) and (j = gTestLogic.State.CurrentCol) then
        DrawOptotypeSelection(ACanvas, lRect);
      DrawFreiburgOptotype(ACanvas, Optotypes[i][j], lRect, i);
    end;

    lHeight := lHeight + INT_TESTDRAWER_VSPACING + lSize;
  end;
end;

{ We can't just StretchDraw the image, because under
  Gtk 1 and 2 this operation is extremely slow,
  so a buffer needs to be kept of all image sizes }
procedure TTestDrawer.DrawFreiburgOptotype(ACanvas: TCanvas;
  ADirection: TDirection; ADestRect: TRect; ASizeCount: Integer);
begin
  case ADirection of
  dNorth:  ACanvas.Draw(ADestRect.Left, ADestRect.Top, ImagesNorth[ASizeCount]);
  dEast:   ACanvas.Draw(ADestRect.Left, ADestRect.Top, ImagesEast[ASizeCount]);
  dSouth:  ACanvas.Draw(ADestRect.Left, ADestRect.Top, ImagesSouth[ASizeCount]);
  dWest:   ACanvas.Draw(ADestRect.Left, ADestRect.Top, ImagesWest[ASizeCount]);
  end;

{  // Code which uses stretching for each painting, too
  //  slow in Gtk
  case ADirection of
  dNorth:  ACanvas.StretchDraw(ADestRect, ImagesNorth[0]);
  dEast:   ACanvas.StretchDraw(ADestRect, ImagesEast[0]);
  dSouth:  ACanvas.StretchDraw(ADestRect, ImagesSouth[0]);
  dWest:   ACanvas.StretchDraw(ADestRect, ImagesWest[0]);
  end;}

{var
  AWidth, AHeight: Integer;
begin
// Possible code to draw the optotype with geometric figures

  AWidth := ADestRect.Right - ADestRect.Left;
  AHeight := ADestRect.Bottom - ADestRect.Top;

  ACanvas.Brush.Color := clWhite;
  ACanvas.FillRect(ADestRect.Left, ADestRect.Top,
    ADestRect.Right, ADestRect.Bottom);
  ACanvas.Pen.Width := AWidth div 4;
  ACanvas.Pen.Color := clBlack;
  ACanvas.Pen.EndCap := pecSquare;
  ACanvas.Arc(
    ADestRect.Left + AWidth div 8,
    ADestRect.Top + AWidth div 8,
    ADestRect.Left + AWidth - AWidth div 8,
    ADestRect.Top + AHeight - AWidth div 8,
    16*30, 16*300);}
end;

procedure TTestDrawer.DrawOptotypeSelection(ACanvas: TCanvas; ADestRect: TRect);
var
  lRect: TRect;
begin
  lRect.Left := ADestRect.Left - 8;
  lRect.Top := ADestRect.Top - 8;
  lRect.Right := ADestRect.Right + 8;
  lRect.Bottom := ADestRect.Bottom + 8;
  ACanvas.Pen.Color := clRed;
  ACanvas.Pen.Width := 5;
  ACanvas.Brush.Style := bsClear;
  ACanvas.Rectangle(lRect);
  ACanvas.Brush.Style := bsSolid;
  ACanvas.Pen.Width := 1;
end;

procedure TTestDrawer.UpdateImage;
begin
  BufBitmap.Width := Width;
  BufBitmap.Height := Height;

  BufBitmap.Canvas.Brush.Color := clWhite;
  BufBitmap.Canvas.Brush.Style := bsSolid;
  BufBitmap.Canvas.FillRect(0, 0, Width, Height);

  DrawTestTable(BufBitmap.Canvas,
   INT_TESTDRAWER_TABLE_HSPACING,
   INT_TESTDRAWER_TABLE_VSPACING);

  Invalidate;
end;

end.

